package bsts.controller;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Date;
import java.util.Iterator;

import bsts.exception.AccountNotFoundException;
import bsts.exception.CustomerNotFoundException;
import bsts.model.Account;
import bsts.model.Customer;
import bsts.model.Interest;
import bsts.model.User;

public class CustomerController {

	private IOController ioController;
	private HashMap<String, Customer> customers = new HashMap<String, Customer>();
	private static int ACCOUNT_COUNT = 0; // need to read frm config

	public CustomerController() {
		ioController = new IOController();
		customers = ioController.RetrieveCustomers();
		ACCOUNT_COUNT = ioController.RetrieveAccountID();
	}

	public void refreshCustomers() {
		customers = ioController.RetrieveCustomers();
	}

	public void registerCustomer(String surname, String firstname,
			String secondname, String nric, String address, String telephoneNo,
			String salutation, ArrayList<Interest> interests) {
		Customer customer = new Customer(surname, firstname, secondname, nric,
				address, telephoneNo, salutation);
		customer.setInterest(interests);

		customers.put(customer.getNric(), customer);
		ioController.UpdateCustomers(customers);
	}

	public Account registerCustomerWithDefAcc(String surname, String firstname,
			String secondname, String nric, String address, String telephoneNo,
			String salutation, ArrayList<Interest> interests, User user) {
		Customer customer = new Customer(surname, firstname, secondname, nric,
				address, telephoneNo, salutation);
		Account account = newAccount(user);
		customer.putAccount(account);
		customer.setInterest(interests);

		customers.put(customer.getNric(), customer);
		ioController.UpdateCustomers(customers);

		return account;
	}

	public Account addAccToCustomer(Customer customer, User user) {
		Account account = newAccount(user);
		customer.putAccount(account);

		// customers.put(customer.getNric(), customer);
		// ioController.UpdateCustomers(customers);

		return account;
	}

	public void updateCustomer(Customer customer) {
		customers.put(customer.getNric(), customer);

		ioController.UpdateCustomers(customers);
	}
	
	public boolean isCustomerExists(String nric) {
		if (customers.get(nric.toUpperCase()) != null) {
			return true;
		} else {
			return false;
		}
	}

	public ArrayList<Customer> getCustomers() {
		ArrayList<Customer> arrCustomers = new ArrayList<Customer>(customers.values());
		// soft by full name
		Collections.sort(arrCustomers);
		return arrCustomers;
	}

	public HashMap<String, Customer> getCustomersMap() {
		return customers;
	}

	public Account newAccount(User user) {
		return new Account(generateAccountNo(), user);
	}

	private String generateAccountNo() {
		SimpleDateFormat sdfYear = new SimpleDateFormat("yyyy");

		String accountNo = sdfYear.format(new Date());
		ACCOUNT_COUNT++;
		ioController.UpdateAccountID(ACCOUNT_COUNT);
		if (ACCOUNT_COUNT < 10) {
			return accountNo + "000" + ACCOUNT_COUNT;
		} else if (ACCOUNT_COUNT < 100) {
			return accountNo + "00" + ACCOUNT_COUNT;
		} else if (ACCOUNT_COUNT < 1000) {
			return accountNo + "0" + ACCOUNT_COUNT;
		} else {
			return accountNo + ACCOUNT_COUNT;
		}
	}

	// Method definition done by Than Htet Aung
	public Account getAccountDetail(String accountNo) {
		Iterator<Customer> iCustomers = getCustomers().iterator();

		while (iCustomers.hasNext()) {
			Customer customer = iCustomers.next();
			Iterator<Account> iAccounts = customer.getAccounts().iterator();
			while (iAccounts.hasNext()) {
				Account account = iAccounts.next();
				if (account.getAccountNo().equals(accountNo)) {
					return account;
				}
			}
		}

		return null;
	}

	public Account getAccount(String accountNo) throws AccountNotFoundException {
		Account account = getAccountDetail(accountNo);

		if (account == null) {
			throw new AccountNotFoundException(
					"Account not found for Account No. " + accountNo + ".");
		} else {
			return account;
		}
	}

	// Method definition done by Than Htet Aung
	public Customer getCustomerDetail(String accountNo) {
		Iterator<Customer> iCustomers = getCustomers().iterator();

		while (iCustomers.hasNext()) {
			Customer customer = iCustomers.next();
			Iterator<Account> iAccounts = customer.getAccounts().iterator();
			while (iAccounts.hasNext()) {
				Account account = iAccounts.next();
				if (account.getAccountNo().equals(accountNo)) {
					return customer;
				}
			}
		}

		return null;
	}

	public Customer getCustomer(String accountNo)
			throws CustomerNotFoundException {
		Customer customer = getCustomerDetail(accountNo);

		if (customer == null) {
			throw new CustomerNotFoundException(
					"Customer not found for Account No. " + accountNo + ".");
		} else {
			return customer;
		}
	}

}
